package smarthouse;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.Vector;

import annotations.Command;
import annotations.Param;

import commands.CommandInterface;
import devices.AbstractDevice;

public class CommandManager {
	
	public static CommandInterface createCommand(int deviceId, int commandId, HashMap<Integer, Object> paramValues){
		
		Vector<AbstractDevice> devices = Smarthouse.getInstance().devices;
		CommandInterface commandInstance=null;
		
		for (AbstractDevice abstractDevice : devices) {
			if (abstractDevice.getId()!=deviceId) continue;
			for (Class<? extends CommandInterface> commandClass : abstractDevice.getCommands()){
				Command c = commandClass.getAnnotation(Command.class);
				if (c.id()!=commandId) continue;
				
				try {
					commandInstance = commandClass.newInstance();
				} catch (Exception e) {
					e.printStackTrace();
				}
				if (commandInstance == null) return null;
				
				for (Field f:commandClass.getDeclaredFields()) {
					if (!f.isAnnotationPresent(Param.class)) continue;
					f.setAccessible(true);
					Param p = f.getAnnotation(Param.class);
					Object value =paramValues.get(p.id());
					try {
						f.set(commandInstance, value);
					} catch (Exception e) {
						e.printStackTrace();
					} 
				}
			}
		}
		return commandInstance;
	}
	
	public static CommandInterface createCommandFromStrings(int deviceId, int commandId, HashMap<Integer, String> paramValuesAsStrings){
		
		Vector<AbstractDevice> devices = Smarthouse.getInstance().devices;
		CommandInterface commandInstance=null;
		
		for (AbstractDevice abstractDevice : devices) {
			if (abstractDevice.getId()!=deviceId) continue;
			for (Class<? extends CommandInterface> commandClass : abstractDevice.getCommands()){
				Command c = commandClass.getAnnotation(Command.class);
				if (c.id()!=commandId) continue;
				
				try {
					commandInstance = commandClass.newInstance();
				} catch (Exception e) {
					e.printStackTrace();
				}
				if (commandInstance == null) return null;
				
				for (Map.Entry<Integer, String> entry : paramValuesAsStrings.entrySet()) {
				    int paramId = entry.getKey();
				    String value = entry.getValue();
				    commandInstance.setFromString(paramId, value);
				}
			}
		}
		return commandInstance;
	}

	public static HashMap<Integer, String> getInitialValuesForCommand(int deviceId, int commandId){
		HashMap<Integer, String> initialValues = new HashMap<Integer, String>();
		Hashtable<Integer, Object> deviceData =	Smarthouse.getInstance().getDeviceData(deviceId);
		
		Vector<AbstractDevice> devices = Smarthouse.getInstance().devices;
		CommandInterface commandInstance=null;
		
		for (AbstractDevice abstractDevice : devices) {
			if (abstractDevice.getId()!=deviceId) continue;
			for (Class<? extends CommandInterface> commandClass : abstractDevice.getCommands()){
				Command c = commandClass.getAnnotation(Command.class);
				if (c.id()!=commandId) continue;
				
				try {
					commandInstance = commandClass.newInstance();
				} catch (Exception e) {
					e.printStackTrace();
				}
				if (commandInstance == null) return null;
				
				for (Field f:commandClass.getDeclaredFields()) {
					if (!f.isAnnotationPresent(Param.class)) continue;
					Param p = f.getAnnotation(Param.class);
					Object value =commandInstance.getInitialValueFor(p.id(), deviceData);
					initialValues.put(p.id(), value.toString());

				}
			}
		}
		return initialValues;
	}
}
